package laxexec

// 主要是抄的kexec

import (
	"errors"
	"os"
	"os/exec"
	"sync"
)

// @Desc: command管理结构
type LaxCommand struct {
	// 真正的exec cmd
	*exec.Cmd
	// cmd执行结果
	cmdExecResult error
	// 调用wait时的等待chan,支持多次调用等待
	waitChan chan error
	// 是否已执行完
	finished bool
	// 停止chan
	stopChan chan os.Signal
	// 初始化一次
	once sync.Once
	// 可能会多次次操作，加锁
	mu sync.Mutex
}

// @Desc: 开跑进程
// @receiver lc
// @return error 执行结果
func (lc *LaxCommand) Run() error  {
	if err := lc.Cmd.Start(); err != nil {
		return err
	}
	return lc.Wait()
}

// @Desc: 也是阻塞等待,支持多次调用
// @return error 进程执行结果
func (lc *LaxCommand) Wait() error {
	if lc.Process == nil {
		return errors.New("进程没有运行")
	}
	lc.once.Do(func() {
		go func() {
			lc.cmdExecResult = lc.Cmd.Wait()
			lc.mu.Lock()
			lc.finished = true
			if lc.waitChan != nil {
				lc.waitChan <- lc.cmdExecResult
			}
			lc.mu.Unlock()
		}()
	})
	lc.mu.Lock()
	if lc.finished {
		lc.mu.Unlock()
		return lc.cmdExecResult
	}
	if lc.waitChan == nil {
		lc.waitChan = make(chan error, 1)
	}
	lc.mu.Unlock()
	return <-lc.waitChan
}

// @Desc: 设置stdout
func (lc *LaxCommand) ConsoleOutput() {
	lc.Stdout = os.Stdout
	lc.Stderr = os.Stderr
}
